import sqlparse
import re
import os

def convert_mysql_to_postgres(mysql_sql_content: str) -> str:
    """
    将 MySQL SQL 语句内容转换为 PostgreSQL 兼容的 SQL 语句内容。
    处理常见的语法差异。
    """
    converted_statements = []

    # sqlparse 将整个 SQL 内容解析成多个独立的语句
    parsed_statements = sqlparse.parse(mysql_sql_content)

    for statement in parsed_statements:
        # 将解析后的语句转换回字符串，以便进行基于文本的替换
        # sqlparse 提供了对Token流的直接操作，但对于复杂替换，基于字符串更直观
        s_str = str(statement).strip()

        if not s_str:
            continue

        # --- 1. 处理 AUTO_INCREMENT ---
        # 匹配 CREATE TABLE ... AUTO_INCREMENT
        # 对于 UNSIGNED，PostgreSQL没有直接对应，通常转换为BIGINT/SERIAL并处理好符号位
        # 这里统一转为BIGSERIAL/SERIAL，简单处理
        s_str = re.sub(r'(\bINT|\bINTEGER|\bSMALLINT|\bMEDIUMINT)\s+UNSIGNED\s+AUTO_INCREMENT\b', r'SERIAL', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'(\bBIGINT)\s+UNSIGNED\s+AUTO_INCREMENT\b', r'BIGSERIAL', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'(\bINT|\bINTEGER|\bSMALLINT|\bMEDIUMINT)\s+AUTO_INCREMENT\b', r'SERIAL', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'(\bBIGINT)\s+AUTO_INCREMENT\b', r'BIGSERIAL', s_str, flags=re.IGNORECASE)


        # --- 2. 处理 LIMIT offset, count ---
        # 匹配 LIMIT 数字, 数字
        s_str = re.sub(r'\s+LIMIT\s+(\d+)\s*,\s*(\d+)\s*', r' OFFSET \1 LIMIT \2 ', s_str, flags=re.IGNORECASE)
        # 匹配 LIMIT 数字 (PostgreSQL中兼容，但为了统一习惯，也可以转为 LIMIT 数字 OFFSET 0)
        # s_str = re.sub(r'\s+LIMIT\s+(\d+)\s*$', r' LIMIT \1 OFFSET 0 ', s_str, flags=re.IGNORECASE)


        # --- 3. 处理反引号 `identifier` 为双引号 "identifier" ---
        # 匹配`xxx`，并替换为"xxx"
        # 注意：这可能会替换掉 SQL 字符串内部的反引号，需要更复杂的解析来避免
        # 简单的正则替换可能不完善，但对于标识符场景有效
        s_str = re.sub(r'`([^`]+)`', r'"\1"', s_str)

        # --- 4. 处理 IF() 函数 ---
        # 这是一个简化的正则表达式，对于复杂的嵌套IF或参数中包含逗号的IF可能不准确
        # 实际生产中，对于这种函数，建议人工检查或使用专门的库。
        if re.search(r'IF\s*\(([^,)]+\s*,\s*[^,)]+\s*,\s*[^)]+)\)', s_str, re.IGNORECASE):
            def replace_if_func(match):
                # 尝试更健壮地解析参数，避免简单split逗号的问题
                # 这种复杂性通常需要真正的SQL解析器，这里只是一个简化的正则尝试
                # 考虑括号嵌套，可能需要计数器来平衡
                # 这里我们假设IF参数不会包含未转义的逗号和不平衡的括号
                parts = []
                balance = 0
                current_part = []
                in_string = False
                for char in match.group(1):
                    if char == "'" or char == '"':
                        in_string = not in_string
                    if not in_string:
                        if char == '(':
                            balance += 1
                        elif char == ')':
                            balance -= 1
                        elif char == ',' and balance == 0:
                            parts.append("".join(current_part).strip())
                            current_part = []
                            continue
                    current_part.append(char)
                if current_part:
                    parts.append("".join(current_part).strip())


                if len(parts) == 3:
                    condition = parts[0].strip()
                    true_val = parts[1].strip()
                    false_val = parts[2].strip()
                    return f"CASE WHEN {condition} THEN {true_val} ELSE {false_val} END"
                return match.group(0) # 不匹配则返回原始字符串
            s_str = re.sub(r'IF\s*\(([^)]+)\)', replace_if_func, s_str, flags=re.IGNORECASE)


        # --- 5. 处理 CURDATE() 函数 ---
        s_str = re.sub(r'\bCURDATE\s*\(\s*\)', r'CURRENT_DATE', s_str, flags=re.IGNORECASE)

        # --- 6. 警告/提示 INSERT ... ON DUPLICATE KEY UPDATE (UPSERT) ---
        # 这是一个复杂转换，通常不能简单正则替换
        if re.search(r'\bON\s+DUPLICATE\s+KEY\s+UPDATE\b', s_str, flags=re.IGNORECASE):
            print(f"警告：检测到 MySQL 的 'ON DUPLICATE KEY UPDATE' 语句。此语句在 PostgreSQL 中需要转换为 'ON CONFLICT DO UPDATE'。请手动检查并修改此语句。\n语句: {s_str[:200]}...") # 打印前200字符
            s_str += f"\n-- WARNING: MySQL 'ON DUPLICATE KEY UPDATE' detected. Convert to PostgreSQL 'ON CONFLICT (...) DO UPDATE' manually."


        # --- 7. 处理 TEXT 类型的长度 (PostgreSQL TEXT 没有长度限制) ---
        s_str = re.sub(r'\bTEXT\s*\(\s*\d+\s*\)', r'TEXT', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bTINYTEXT\b', r'TEXT', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bMEDIUMTEXT\b', r'TEXT', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bLONGTEXT\b', r'TEXT', s_str, flags=re.IGNORECASE)

        # --- 8. BLOB 类型转换 ---
        s_str = re.sub(r'\bBLOB\s*\(\s*\d+\s*\)', r'BYTEA', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bTINYBLOB\b', r'BYTEA', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bMEDIUMBLOB\b', r'BYTEA', s_str, flags=re.IGNORECASE)
        s_str = re.sub(r'\bLONGBLOB\b', r'BYTEA', s_str, flags=re.IGNORECASE)


        converted_statements.append(s_str)

    return "\n\n".join(converted_statements)

# --- 主程序入口 ---
if __name__ == "__main__":
    # 直接指定输入和输出文件路径
    input_file_name = "ry_20250522_snowflake.sql"
    output_file_name = "ry_20250522_snowflake_postgresql.sql"

    # 假设脚本和 SQL 文件在同一目录下
    current_directory = os.path.dirname(os.path.abspath(__file__))
    input_path = os.path.join(current_directory, input_file_name)
    output_path = os.path.join(current_directory, output_file_name)

    if not os.path.exists(input_path):
        print(f"错误：输入文件 '{input_path}' 不存在。请确保文件位于脚本的相同目录或提供正确路径。")
        exit(1)

    try:
        with open(input_path, 'r', encoding='utf-8') as f:
            mysql_content = f.read()

        print(f"正在转换文件: '{input_file_name}' -> '{output_file_name}'...")
        postgres_content = convert_mysql_to_postgres(mysql_content)

        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(postgres_content)

        print(f"转换完成！结果已成功保存到: '{output_path}'")

    except Exception as e:
        print(f"转换过程中发生错误: {e}")